package org.erp.product.strategy.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.erp.common.annotation.StockLockBatch;
import org.erp.common.constant.ProductConstant;
import org.erp.common.context.StockLockContext;
import org.erp.common.enums.DeviceInventoryEvent;
import org.erp.product.domain.dto.ConnectLogTriageDto;
import org.erp.product.domain.entity.ConnectLog;
import org.erp.product.domain.entity.ProductInfo;
import org.erp.product.domain.entity.RepairInfo;
import org.erp.product.infrastructure.convert.ProductInfoConvert;
import org.erp.product.infrastructure.convert.RepairInfoConvert;
import org.erp.product.infrastructure.enums.ConnectEventEnum;
import org.erp.product.infrastructure.enums.InspectionEventEnum;
import org.erp.product.infrastructure.enums.RepairEventEnum;
import org.erp.product.infrastructure.enums.TransferTypeEnum;
import org.erp.product.service.ConnectLogService;
import org.erp.product.service.ProductInfoService;
import org.erp.product.service.RepairInfoService;
import org.erp.product.service.TransferLogService;
import org.erp.product.strategy.ConnectActionStrategy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Log4j2
@Service(value = "CONNECTION")
@AllArgsConstructor
public class ConnectionConnectActionStrategy implements ConnectActionStrategy {

    private final ConnectLogService connectLogService;

    private final ProductInfoService productInfoService;

    private final RepairInfoService repairInfoService;

    private final TransferLogService transferLogService;

    private final RepairInfoConvert repairInfoConvert;

    private final ProductInfoConvert productInfoConvert;

    @StockLockBatch(directIds = true, busyKey = ProductConstant.PRODUCT_BUSY_CONNECT_LOGS)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void execute(List<Long> ids) {
        List<ConnectLog> connectLogList = connectLogService.searchAndVerify(ids, ConnectEventEnum.CONNECTION);
        ConnectLogTriageDto triageDto = connectLogService.triage(connectLogList);
        // 处理仓库来源数据
        if (!triageDto.getWarehouseList().isEmpty()) {
            StockLockContext.setHasExternal(true);
            connectLogService.handleWarehouse(triageDto.getWarehouseList(), DeviceInventoryEvent.HANDOVER);
        }
        // 处理非仓库来源数据
        if (!triageDto.getNonWarehouseList().isEmpty()) {
            //设置内部ids
            StockLockContext.setInternalIds(triageDto.getNonWarehouseList().stream().map(ConnectLog::getId).map(String::valueOf).toList());
            //更改接驳状态
            connectLogService.updateStatus(triageDto.getNonWarehouseList(), ConnectEventEnum.CONNECTION);
            List<ConnectLog> repairConnectList = new ArrayList<>();
            List<ConnectLog> inspectionConnectList = new ArrayList<>();
            connectLogList.forEach(c -> {
                if (TransferTypeEnum.REPAIR_TRANSFER.getCode().equals(c.getTransferType())) {
                    repairConnectList.add(c);
                } else {
                    inspectionConnectList.add(c);
                }
            });
            List<RepairInfo> repairList;
            List<ProductInfo> productList;
            if (!repairConnectList.isEmpty()) {
                repairList = repairConnectList.stream().map(repairInfoConvert::convert).toList();
                //todo 判断操作人为同一人时改状态为 待维修 不是做新增
                Set<Long> stockIds = repairList.stream().map(RepairInfo::getStockId).collect(Collectors.toSet());
                List<RepairInfo> existRepairList = repairInfoService.list(new QueryWrapper<RepairInfo>().lambda()
                        .in(RepairInfo::getStockId, stockIds));
                repairInfoService.updateBatchStatus(existRepairList, RepairEventEnum.CONNECT);
                repairInfoService.saveBatch(repairList);
            }
            List<ProductInfo> existProductList;
            List<ProductInfo> unexistProductList;
            if (!inspectionConnectList.isEmpty()) {
                productList = inspectionConnectList.stream().map(productInfoConvert::convert).toList();
                Set<Long> stockIds = productList.stream().map(ProductInfo::getStockId).collect(Collectors.toSet());
                existProductList = productInfoService.list(new QueryWrapper<ProductInfo>().lambda()
                        .in(ProductInfo::getStockId, stockIds));
                List<Long> existStockIds = existProductList.stream().map(ProductInfo::getStockId).toList();
                unexistProductList = productList.stream()
                        .filter(p -> existStockIds.contains(p.getStockId())).toList();
                if (!existProductList.isEmpty()) {
                    // 根据不同调拨类型更改状态
                    Map<Integer, List<ProductInfo>> listMap = existProductList.stream()
                            .collect(Collectors.groupingBy(ProductInfo::getTransferType));
                    if (!listMap.get(TransferTypeEnum.REPAIR_TRANSFER.getCode()).isEmpty()) {
                        List<ProductInfo> repairTypeList = listMap.get(TransferTypeEnum.REPAIR_TRANSFER.getCode());
                        productInfoService.updateBatchStatus(repairTypeList, InspectionEventEnum.REPAIR_CONNECT);
                    } else if (!listMap.get(TransferTypeEnum.SELL_TRANSFER.getCode()).isEmpty()) {
                        List<ProductInfo> sellTypeList = listMap.get(TransferTypeEnum.SELL_TRANSFER.getCode());
                        productInfoService.updateBatchStatus(sellTypeList, InspectionEventEnum.SELL_CONNECT);
                    } else if (!listMap.get(TransferTypeEnum.DICKER_TRANSFER.getCode()).isEmpty()) {
                        List<ProductInfo> dickerTypeList = listMap.get(TransferTypeEnum.DICKER_TRANSFER.getCode());
                        productList.forEach(p -> {
                            dickerTypeList.forEach(d -> {
                                if (p.getStockId().equals(d.getStockId())) {
                                    d.setDickerPrice(p.getDickerPrice());
                                }
                            });
                        });
                        productInfoService.updateBatchStatus(dickerTypeList, InspectionEventEnum.INSPECTION_DICKER_CONNECT);
                    } else if (!listMap.get(TransferTypeEnum.INSPECTION_TRANSFER.getCode()).isEmpty()) {
                        List<ProductInfo> inspectionTypeList = listMap.get(TransferTypeEnum.INSPECTION_TRANSFER.getCode());
                        productInfoService.updateBatchStatus(inspectionTypeList, InspectionEventEnum.INSPECTION_DICKER_CONNECT);
                    }
                }
                productInfoService.saveBatch(unexistProductList);
            }
            //todo 操作日志
//            TransferLogAddDto transferLogAddDto = new TransferLogAddDto();
//            existProductList.addAll(unexistProductList);
//            transferLogAddDto.setProductInfoList(existProductList);
//            transferLogAddDto.setRepairInfoList(repairList);
//            transferLogAddDto.setConnectOldStatus(connectLogList.get(0).getOldStatus());
//            transferLogAddDto.setConnectNewStatus(connectLogList.get(0).getNewStatus());
//            transferLogAddDto.setOperationId(connectLogList.get(0).getOperationId());
//            transferLogAddDto.setOperationName(connectLogList.get(0).getOperationName());
//            transferLogAddDto.setOldStatus(-1);
//            transferLogService.saveBatch(transferLogAddDto, EventCodeEnum.CONNECT, ConnectEventEnum.CONNECTION);
        }
    }
}
